import math
import os

import bpy
import mathutils

import sys;sys.path.append(r'C:\Program Files\eclipse\plugins\org.python.pydev.debug_2.2.1.2011071313\pysrc')
import pydevd

from bpy_extras.io_utils import create_derived_objects, free_derived_objects

import xml.etree.cElementTree as ET

##########################################################
# Functions for writing output file
##########################################################

def indent(elem, level=0):
    i = "\n" + level*"  "
    if len(elem):
        if not elem.text or not elem.text.strip():
            elem.text = i + "  "
        for e in elem:
            indent(e, level+1)
            if not e.tail or not e.tail.strip():
                e.tail = i + "  "
        if not e.tail or not e.tail.strip():
            e.tail = i
    else:
        if level and (not elem.tail or not elem.tail.strip()):
            elem.tail = i


class dav_class:

    def __init__(self, filepath):
        self.global_matrix = mathutils.Matrix.Rotation(-(math.pi / 2.0), 4, 'X')
        
        self.rootEl = ET.Element("dav")
        self.sceneEl = ET.SubElement(self.rootEl, "scene")

        #--- class private don't touch ---
        self.filepath = filepath
        self.file = open(self.filepath, "w", encoding="utf8", newline="\n")

##########################################################
# Writing nodes routines
##########################################################

    def writeIndexedFaceSet(self, ob, mesh, mtx, world, EXPORT_TRI=False):
        fw = self.file.write
        mesh_name_dav = ob.name

        if not mesh.faces:
            return

        loc, quat, sca = mtx.decompose()
                
        objEl = ET.SubElement(self.sceneEl, "object")
        objEl.attrib["name"] = mesh_name_dav
        #objEl.text = mesh_name_dav
        
        
        transformationEl = ET.SubElement( objEl, "transformation" )    
        transformationEl.attrib["_00"] = str(mtx[0][0])  
        transformationEl.attrib["_01"] = str(mtx[0][1])  
        transformationEl.attrib["_02"] = str(mtx[0][2])  
        transformationEl.attrib["_03"] = str(mtx[0][3])  
            
        transformationEl.attrib["_10"] = str(mtx[1][0])  
        transformationEl.attrib["_11"] = str(mtx[1][1])  
        transformationEl.attrib["_12"] = str(mtx[1][2])  
        transformationEl.attrib["_13"] = str(mtx[1][3])     
        
        transformationEl.attrib["_20"] = str(mtx[2][0])  
        transformationEl.attrib["_21"] = str(mtx[2][1])  
        transformationEl.attrib["_22"] = str(mtx[2][2])  
        transformationEl.attrib["_23"] = str(mtx[2][3])  
            
        transformationEl.attrib["_30"] = str(mtx[3][0])  
        transformationEl.attrib["_31"] = str(mtx[3][1])  
        transformationEl.attrib["_32"] = str(mtx[3][2])  
        transformationEl.attrib["_33"] = str(mtx[3][3])  
        
        posEl = ET.SubElement( objEl, "position" )    
        posEl.attrib["x"] = str(loc[0])
        posEl.attrib["y"] = str(loc[1])
        posEl.attrib["z"] = str(loc[2])
        posEl.attrib["w"] = str(1.0) #v.co[3])  
        
        scaleEl = ET.SubElement( objEl, "scale" )    
        scaleEl.attrib["x"] = str(sca[0])
        scaleEl.attrib["y"] = str(sca[1])
        scaleEl.attrib["z"] = str(sca[2])
        scaleEl.attrib["w"] = str(1.0) #v.co[3])    
        
        normQuat = quat.normalized();
        orientationEl = ET.SubElement( objEl, "orientation" )    
        orientationEl.attrib["x"] = str(normQuat[0])
        orientationEl.attrib["y"] = str(normQuat[1])
        orientationEl.attrib["z"] = str(normQuat[2])
        orientationEl.attrib["w"] = str(normQuat[3])    
        
        for v in mesh.vertices:  
            vertEl = ET.SubElement( objEl, "vertex" )
            vertEl.attrib["x"] = str(v.co[0])
            vertEl.attrib["y"] = str(v.co[2])
            vertEl.attrib["z"] = str(0.0) #v.co[1])
            vertEl.attrib["w"] = str(1.0) #v.co[3])
     
        mesh_faces = mesh.faces[:]
        for f in mesh_faces:
            faceEl = ET.SubElement( objEl, "face" )
            face = f.vertices[:]
            for vi in face:
                vertIdxEl = ET.SubElement( faceEl, "vertex" )
                vertIdxEl.attrib["idx"] = str(vi)
                
        # Just adding a comment to make a change to test source control
                
        
        pydevd.settrace()
        
        if "infiniteMass" in ob:
            objEl.attrib["infiniteMass"] = "true"
        else:
            objEl.attrib["infiniteMass"] = "false"            

        fw("shape %s\n" % mesh_name_dav)
        fw("trans %.6f %.6f %.6f\n" % loc[:])
        fw("scale %.6f %.6f %.6f\n" % sca[:])
        fw("rot %.6f %.6f %.6f %.6f\n" % quat.normalized()[:])

        for v in mesh.vertices:
            fw("vert %.6f %.6f %.6f\n" % v.co[:])

        mesh_faces = mesh.faces[:]
        for i in mesh_faces:
            fv = i.vertices[:]
            if len(fv) == 3:
                fw("face %i %i %i\n" % fv)
            else:
                fw("face %i %i %i %i\n" % fv)

        fw("\n")

##########################################################
# export routine
##########################################################

    def export(self, scene, world,
                use_apply_modifiers=False,
                use_selection=True,
                EXPORT_TRI=False,
                ):

        # tag un-exported IDs
        bpy.data.meshes.tag(False)
        bpy.data.materials.tag(False)
        bpy.data.images.tag(False)

        print("Info: starting Dav export to %r..." % self.filepath)

        if use_selection:
            objects = (o for o in scene.objects if o.is_visible(scene) and o.select)
        else:
            objects = (o for o in scene.objects if o.is_visible(scene))

        for ob_main in objects:

            free, derived = create_derived_objects(scene, ob_main)

            if derived is None:
                continue

            for ob, ob_mat in derived:
                objType = ob.type
                objName = ob.name
                ob_mat = self.global_matrix * ob_mat

                if objType in ('MESH', 'CURVE', 'SURF', 'FONT'):
                    if (objType != 'MESH') or (use_apply_modifiers and ob.is_modified(scene, 'PREVIEW')):
                        try:
                            me = ob.to_mesh(scene, use_apply_modifiers, 'PREVIEW')
                        except:
                            me = None
                    else:
                        me = ob.data

                    if me is not None:
                        self.writeIndexedFaceSet(ob, me, ob_mat, world, EXPORT_TRI=EXPORT_TRI)

                        # free mesh created with create_mesh()
                        if me != ob.data:
                            bpy.data.meshes.remove(me)

                else:
                    #print "Info: Ignoring [%s], object type [%s] not handle yet" % (object.name,object.getType)
                    pass

            if free:
                free_derived_objects(ob_main)                
                
        self.file.write("\n")

        self.file.close()
        print("Info: finished Dav export to %r" % self.filepath)

##########################################################
# Callbacks, needed before Main
##########################################################
    

def save(operator, context, filepath="",
          use_selection=True,
          use_apply_modifiers=False,
          use_triangulate=False):
#def save( context, filepath="",
#          use_selection=True,
#          use_apply_modifiers=False,
#          use_triangulate=False):

    if not filepath.lower().endswith('.dav'):
       filepath = '.'.join(filepath.split('.')[:-1]) + '.dav'       
       
    
    #class vert1:    
    #    x=1
    #    y=2
    #    z=3
    #    w=4
    
    #class vert2:
    #    x=5
    #    y=6
    #    z=7
    #    w=8
    
    #class vert3:    
    #    x=9
    #    y=10
    #    z=11
    #    w=12
    
    #class vert4:    
    #    x=13
    #    y=14
    #    z=15
    #    w=16
    
    #verts = [vert1,vert2,vert3,vert4]   
    
    # build a tree structure
    #rootEl = ET.Element("dav")

    #sceneEl = ET.SubElement(rootEl, "scene")
    
    #for obj in ["floor","box1","box2"]:
    #    objEl = ET.SubElement(sceneEl, "obj")
    #    objEl.text = obj
    #    for vert in verts:            
    #        vertEl = ET.SubElement( objEl, "vert" )
    #        vertEl.attrib["x"] = str(vert.x)
    #        vertEl.attrib["y"] = str(vert.y)
    #        vertEl.attrib["z"] = str(vert.z)
    #        vertEl.attrib["w"] = str(vert.w)
            
        
    # wrap it in an ElementTree instance, and save as XML
    
    #tree = ET.ElementTree(rootEl)
    #indent(tree.getroot())
    #tree.write(r"C:\temp\test.dav","utf-8")
    #tree.write(r"C:\temp\test.dav"encoding="us-ascii", xml_declaration=None, method="xml")


    
    

    scene = context.scene
    world = scene.world

    if bpy.ops.object.mode_set.poll():
        bpy.ops.object.mode_set(mode='OBJECT')
    
    

    wrlexport = dav_class(filepath)
    wrlexport.export(scene,
                     world,
                     use_apply_modifiers=use_apply_modifiers,
                     use_selection=use_selection,
                     EXPORT_TRI=use_triangulate,
                     )
    
    tree = ET.ElementTree(wrlexport.rootEl)
    indent(tree.getroot())
    tree.write(filepath,"utf-8")
    #tree.write(r"C:\temp\test.dav","utf-8")    


    return {'FINISHED'}


#save( bpy.context, r'C:\Resources\untitled.dav' )
